Le carnet On est
Annale · session normale 2024-2025 · ING2 GIA FA

Examen C++ 2024 — 2025 · GIA FA

Quatre exercices avec corrigé partiel intégré au PDF : passage de paramètres, classe Image (surcharge operator[]), polymorphisme (Polygone / Rectangle / override), simulation des urgences d'un hôpital avec priority_queue STL.

2h · ING2 GIA FA 4 exercices · 20 pts Aucun document autorisé

i. Sujet & corrigé partiel

Le corrigé est intégré directement dans le PDF (en violet sous chaque question). Le sujet et la correction partagent le même document.

Le PDF ne s'affiche pas. Télécharger.

↗ Ouvrir en plein écran

ii. Notions mobilisées

ExoSujetNotion cléChapitre
1Passage de paramètres (int c, int *c, int &c)Valeur, pointeur, référenceSE1
2Classe Image (short** a)Constructeur de copie, opérateur =, règle de troisSE2 §5
static short& operator[](int i)Surcharge de [] renvoyant une référence, staticSE3
3Polygone / Rectangle avec virtual et overridePolymorphisme dynamique, signatures correctesSE4 §6
4Simulation urgences hôpitalClasse abstraite Objet (virtuelle pure), héritageSE4 §7
priority_queue + foncteur de comparaison + exceptionsSTL, foncteurs, try/catch sur saisieSE7 · SE6

iii. Repères de correction

Exercice 1 — Passage de paramètres (2 pts)

Pour void ajouter(int a, int b, int c) { c = a+b; } sur ajouter(1, -2, 0) :

  • (a) par valeur : c = 0 dans le main (la modification reste locale)
  • (c) par référence (int &c) : c = -1 dans le main (alias direct, la modification est visible)

Appellations : copie de valeur pour a, b · copie de référence pour le cas (c).

Exercice 2 — Classe Image (6 pts)

class Image {
   short** a;
   int nlignes, ncols;
public:
   Image();
   Image(int m, int n);
   Image(const Image&);              // constructeur de copie
   Image& operator=(const Image&);  // affectation
   ~Image();
   static short& operator[](int i) { return a[i]; }
};
  • Q1-Q4 : expliquer chaque méthode (constructeur, copy-ctor, operator=, destructeur). Cf. règle de trois — toute classe qui gère de la mémoire dynamique (new) doit définir les trois.
  • Q5 : la classe est-elle canonique ? Oui si les 4 méthodes sont présentes et corrigées : ctor par défaut, ctor de copie, operator=, destructeur. Le sujet en demande la justification.
  • Q6 : operator[] est un opérateur de surcharge d'indice. short& renvoie une référence vers a[i], ce qui permet d'écrire img[3] = 42.
  • Q7 : le mot-clé static indique que la méthode est une méthode de classe, pas d'instance. Discutable ici (l'operator[] a besoin d'accéder à a) — le sujet pose la question pour faire réfléchir au problème.

Exercice 3 — Polymorphisme (4 pts)

Code donné : hiérarchie Polygone → Rectangle avec une série de méthodes virtuelles, certaines redéclarées avec override.

class Polygone {
   virtual void perimetre();
   virtual void aire() const;
   virtual void tauxOccupation(int = 0);
   void         espaceDiponible();
};

class Rectangle : public Polygone {
   virtual void perimetre();
   virtual void aire();
   virtual void perimetre() override;            // ligne 17
   virtual void tauxOccupation(double = 0.0);
   virtual void aire() override;                  // ligne 19
   virtual void tauxOccupation(double = 0.0) override;  // ligne 20
   void         espaceDiponible() override;        // ligne 21
};

Lignes 15-21 : justes ou fausses ?

  • L15 virtual void perimetre(); : juste — redéclaration valide d'une méthode virtuelle de la base, le polymorphisme fonctionne.
  • L16 virtual void aire(); : fausse — la base a aire() const, la fille perd le const donc signature différente = nouvelle méthode (pas un override). Compile mais ne polymorphe pas.
  • L17 perimetre() override; : erreur de compilationperimetre est déjà déclarée à L15, double déclaration.
  • L18-19-20 : redéclarations multiples, ambiguës.
  • L21 espaceDiponible() override; : erreur — la base Polygone::espaceDiponible n'est pas virtuelle, on ne peut pas la marquer override.
Leçon clé Le mot-clé override demande au compilateur de vérifier qu'on redéfinit bien une méthode virtuelle existante avec la même signature exacte. Toute divergence (const, type de paramètre, méthode non virtuelle dans la base) déclenche une erreur. C'est précieux pour éviter les bugs silencieux.

Exercice 4 — Urgences hôpital avec priority_queue (8 pts)

Programme complet à fournir (4 fichiers). Structure :

// objet.h — classe abstraite (1 pt)
class Objet {
public:
   virtual void afficher() = 0;
};

// malade.cpp — hérite d'Objet (3 pts)
#include "objet.h"
class Malade : public Objet {
   int id, gravite;
public:
   Malade(int _id, int _gr) : id(_id), gravite(_gr) {}
   virtual void afficher() override {
      cout << "id=" << id << " gravite=" << gravite;
   }
};

// comparaison.cpp — foncteur
class Comparaison {
public:
   bool operator()(const Malade& m1, const Malade& m2) {
      return m1.priority < m2.priority;
   }
};

// filegravitemalade.cpp — héritage + STL (4 pts)
class FileGraviteMalades : public Objet {
public:
   priority_queue<Malade, vector<Malade>, Comparaison> gq;
   virtual void afficher() override {
      Malade m;
      auto gq_temp = gq;
      while (!gq_temp.empty()) {
         m = gq_temp.top();
         m.afficher();
         gq_temp.pop();
      }
   }
};

Main avec saisie sécurisée par exception (saisirInt avec throw/catch) :

int saisirInt(string message, int NM, int min, int max) {
   int a;
   while (1) {
      try {
         cout << message << NM << " entre : " << min << " et " << max;
         cin >> a;
         cin.clear();                          // reset eventual fail bits
         if (a < min || a > max) throw(10);
         return a;
      } catch (int b) {
         cout << "erreur de saisie" << endl;
      }
   }
}

int main(int argc, char** argv) {
   int nbMalades = atoi(argv[1]);
   FileGraviteMalades fgm;
   for (int i = 0; i < nbMalades; i++) {
      int gravite = saisirInt("entrer la gravité du malade : ", i + 1, 1, 5);
      Malade m(i + 1, gravite);
      fgm.gq.push(m);
   }
   while (!fgm.gq.empty()) {                // traiter par gravité décroissante
      cout << fgm.gq.top() << endl;
      fgm.gq.pop();
   }
   return 0;
}

Compilation : g++ *.cpp -Wall -o gestionUrgence · Exécution : ./gestionUrgence 6.

Notions ré-activées

  • Passage par valeur / pointeur / référence : void f(int c) vs void f(int* c) vs void f(int& c)
  • Règle de trois : ctor de copie + operator= + destructeur dès qu'il y a du new
  • Surcharge operator[] avec retour T& pour permettre l'écriture indexée
  • Classe abstraite avec virtual void m() = 0
  • override exige une signature exacte (même const, mêmes types)
  • On ne peut pas override une méthode non-virtuelle de la base
  • priority_queue<T, vector<T>, Comparator> avec foncteur operator()
  • top() + pop() pour dépiler le plus prioritaire
  • Saisie sécurisée : try { cin>>a; if (...) throw; } catch (int)